package cn.sinjet.phone;

import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.mgroup.wazehelper.R;

import android.content.AsyncQueryHandler;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.provider.ContactsContract;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import cn.sinjet.carassist.SinjetApplication;
import cn.sinjet.communication.bluetooth.BluetoothModel;
import cn.sinjet.utils.ContactNameUtil;
import cn.sinjet.viewmodel.ViewModel;

public class PhoneModel {
	static PhoneModel instance = null;
	private List<Contact> allContacts = null;//new ArrayList<Contact>();
	private List<CallLog> callLogs = null;//new ArrayList<CallLog>();
	Context context;
	private AsyncQueryHandler asyncQueryHandler; // 异步查询数据库类对象  
	private AsyncQueryHandler  asyncQueryCalllog; // 异步查询数据库类对象  
	private Map<Integer, Contact> contactIdMap = null; 
	private static final String tag = "phone";
	int oldPhoneState = TelephonyManager.CALL_STATE_IDLE;
	private boolean isCalllogNeedUpdate = false;
	private boolean mIsContactsLoaded = false;
	private boolean mIsCalllogFirstLoaded = false;
//	private PhoneStateListener mPhoneStateListener;
	int mPhoneState = 0x00;//default   0x01:incoming 0x02:outgoing 0x03:speaking
	String mCallName = "";
	PhoneReceiver mPhoneReceiver = new PhoneReceiver();
	MyPhoneStateListener  mPhoneStateListener = new MyPhoneStateListener();
	public PhoneModel(Context context){
		this.context = context;
         IntentFilter filter = new IntentFilter();
         filter.addAction("android.intent.action.PHONE_STATE");
         filter.addAction("android.intent.action.NEW_OUTGOING_CALL");
         context.registerReceiver(mPhoneReceiver, filter);
	}
	
    public static PhoneModel getIns(Context context){
    	if(instance == null)
    		instance = new PhoneModel(context);
    	return instance;
    }
    
    public void uninit(){
    	context.unregisterReceiver(mPhoneReceiver);
    }
    
    public class PhoneReceiver extends BroadcastReceiver{
        final String tag = "Phone";
        int oldPhoneState = 0;
    	@Override
    	public void onReceive(Context context, Intent intent) {
    		// TODO Auto-generated method stub
    		String action = intent.getAction();
//    		Log.d(tag, "onReceive: "+action);
    		if(Intent.ACTION_NEW_OUTGOING_CALL.equals(action)){
//    			Log.i(tag, "outgoing:"+);
    			onOutgoing(intent.getStringExtra(Intent.EXTRA_PHONE_NUMBER));
    		}else{
    			Log.i(tag, "other phone state: "+action);
    			TelephonyManager telephonyMgr = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);  
    	        // Registers a listener object to receive notification of changes in  
    	        // specified telephony states  
    	        // 建立一个监听器来实时监听电话的通话状态  
    	        telephonyMgr.listen(mPhoneStateListener,  
    	                PhoneStateListener.LISTEN_CALL_STATE);
    		}
    	}
    }
    
   
    public String getContactNameFromPhoneBook(Context context, String phoneNum) {  
        String contactName = "";  
        ContentResolver cr = context.getContentResolver();  
        Cursor pCur = cr.query(  
                ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,  
                ContactsContract.CommonDataKinds.Phone.NUMBER + " = ?",  
                new String[] { phoneNum }, null);  
        if (pCur.moveToFirst()) {  
            contactName = pCur  
                    .getString(pCur  
                            .getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));  
            pCur.close();  
        }  
        return contactName;  
    }  
    
    void getAndSendContactName(final String phoneNum){
    	 if(phoneNum.isEmpty()) return;
    	 new Thread(new Runnable() {
			
			@Override
			public void run() {
				// TODO Auto-generated method stub
				Log.e(tag,"thread to read contact name");
				ContactNameUtil util = new ContactNameUtil();
				mCallName = util.getContackNameByPhone(SinjetApplication.getInstance(), phoneNum);
//				mCallName = getContactNameFromPhoneBook(SinjetApplication.getInstance(), phoneNum);
				Log.e(tag, "Contact name:"+mCallName);
				send2ServiceCallName(mCallName);
			}
		}).start();
    }
    public class MyPhoneStateListener  extends PhoneStateListener {
    	@Override
    	public void onCallStateChanged(int state, String incomingNumber) {
    		// TODO Auto-generated method stub
    		super.onCallStateChanged(state, incomingNumber);
    		 switch (state) {  
             // 当处于待机状态中  
             case TelephonyManager.CALL_STATE_IDLE: {  
                 Log.e(tag, "CALL_STATE_IDLE");
                 mPhoneState = 0;
                 send2ServicePhoneState(mPhoneState);
                 if(oldPhoneState != TelephonyManager.CALL_STATE_IDLE){
                	  new Handler().postDelayed(new Runnable() {
						
						@Override
						public void run() {
							// TODO Auto-generated method stub
						      loadCalllog();
						}
					}, 3000);
                 }
//                 view.append("CALL_STATE_IDLE " + "/n");  
                 break;  
             }  
             // 当处于通话中  
             case TelephonyManager.CALL_STATE_OFFHOOK: {  
                 Log.e(tag, "CALL_STATE_OFFHOOK "+incomingNumber);  
                 mPhoneState = 3;
                 if(oldPhoneState != state){
                	  send2ServicePhoneState(mPhoneState);
                	  if(!incomingNumber.isEmpty())
                      getAndSendContactName(incomingNumber);
                 }
//                 view.append("CALL_STATE_OFFHOOK" + "/n");  
                 break;  
             }  
             // 当处于拨号状态中..    //incomming number
             case TelephonyManager.CALL_STATE_RINGING: {  
                 Log.e(tag, "CALL_STATE_RINGING "+incomingNumber);  
//                 view.append("CALL_STATE_RINGING" + "/n");  
                 mPhoneState = 1;
                 send2ServicePhoneState(mPhoneState);
                 if(!incomingNumber.isEmpty())
                 getAndSendContactName(incomingNumber);
                 break;  
             }  
             default:  
                 break;  
             }  
           oldPhoneState = state;
    	}
    }
    public void onOutgoing(String number){
    	mPhoneState = 0x02;
    	send2ServicePhoneState(mPhoneState);
        getAndSendContactName(number);
    }
    public void loadContacts(){
        if(mIsContactsLoaded) return;
		asyncQueryHandler = new MyAsyncQueryHandler(context.getContentResolver());
//    	new Thread(new Runnable() {
//			
//			@Override
//			public void run() {
				// TODO Auto-generated method stub
		    	Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; // 联系人Uri；
				// 查询的字段
				String[] projection = { ContactsContract.CommonDataKinds.Phone._ID,
						ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
						ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key",
						ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
						ContactsContract.CommonDataKinds.Phone.PHOTO_ID,
						ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY };
				// 按照sort_key升序查詢
				asyncQueryHandler.startQuery(0, null, uri, projection, null, null,
						"sort_key COLLATE LOCALIZED asc");		
//			}
//		}).start();
    	
    }
    
    public void loadCalllog() {
		 asyncQueryCalllog  = new CalllogAsyncQueryHandler(context.getContentResolver());
		 Uri uri = android.provider.CallLog.Calls.CONTENT_URI;  
	        // 查询的列  
	        String[] projection = { android.provider.CallLog.Calls.DATE, // 日期  
	        		android.provider.CallLog.Calls.NUMBER, // 号码  
	        		android.provider.CallLog.Calls.TYPE, // 类型  
	        		android.provider.CallLog.Calls.CACHED_NAME, // 名字  
	        		android.provider.CallLog.Calls._ID, // id  
	        };  
	        asyncQueryCalllog.startQuery(0, null, uri, projection, null, null,  
	        		android.provider.CallLog.Calls.DEFAULT_SORT_ORDER);
	}
    
    public List<Contact> getContacts(){
    	//if(allContacts == null) allContacts = new ArrayList<Contact>();
    	return allContacts;
    }
    private class MyAsyncQueryHandler extends AsyncQueryHandler {

		public MyAsyncQueryHandler(ContentResolver cr) {
			super(cr);
		}

		@Override
		protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
			if (cursor != null && cursor.getCount() > 0) {
				contactIdMap = new HashMap<Integer, Contact>();
				allContacts = new ArrayList<Contact>();
				cursor.moveToFirst(); // 游标移动到第一项
				for (int i = 0; i < cursor.getCount(); i++) {
					cursor.moveToPosition(i);
					String name = cursor.getString(1);
					String number = cursor.getString(2);
					String sortKey = cursor.getString(3);
					int contactId = cursor.getInt(4);
					Long photoId = cursor.getLong(5);
					String lookUpKey = cursor.getString(6);
					if (contactIdMap.containsKey(contactId)) {
						// 无操作
					} else {
						// 创建联系人对象
						Contact contact = new Contact();
						contact.setName(name);
						contact.setNumber(number);
						contact.setSortKey(sortKey);
						contact.setPhotoId(photoId);
						contact.setLookUpKey(lookUpKey);
//						Log.d("contact", "read contact:"+name+"No:"+number);
						allContacts.add(contact);
						contactIdMap.put(contactId, contact);
						
					}
				}
				if (allContacts.size() > 0) {
//					setAdapter(allContacts);
					Log.d("contact", "load contacts size:"+allContacts.size());
					ViewModel.getIns().refreshView(R.id.phone_contact_list);
					ViewModel.getIns().setViewVisible(R.id.phonebook_loading_progress,0);
					mIsContactsLoaded = true;
				}
			}
			super.onQueryComplete(token, cookie, cursor);
		}
	}
    
    public void setCalllogUpdated(){
    	isCalllogNeedUpdate = false;
    }
    public boolean isCallogNeedUpdate(){
    	return isCalllogNeedUpdate;
    }
    private class CalllogAsyncQueryHandler extends AsyncQueryHandler  {
		public CalllogAsyncQueryHandler(ContentResolver cr) {
			super(cr);
		}
         
		@Override
		protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
			Log.d("contact", "onQueryComplete:");
			if (cursor != null && cursor.getCount() > 0) {
				Log.d("contact", "count:"+cursor.getCount());
                callLogs = new ArrayList<CallLog>();  
                SimpleDateFormat sfd = new SimpleDateFormat("MM-dd hh:mm");  
                Date date;  
                cursor.moveToFirst(); // 游标移动到第一项  
                for (int i = 0; i < cursor.getCount(); i++) {  
                    cursor.moveToPosition(i);  
                    date = new Date(cursor.getLong(cursor  
                            .getColumnIndex(android.provider.CallLog.Calls.DATE)));  
                    String number = cursor.getString(cursor  
                            .getColumnIndex(android.provider.CallLog.Calls.NUMBER));  
                    int type = cursor.getInt(cursor  
                            .getColumnIndex(android.provider.CallLog.Calls.TYPE));  
                    String cachedName = cursor.getString(cursor  
                            .getColumnIndex(android.provider.CallLog.Calls.CACHED_NAME));// 缓存的名称与电话号码，如果它的存在  
                    int id = cursor.getInt(cursor  
                            .getColumnIndex(android.provider.CallLog.Calls._ID));  
  
                    CallLog callLogBean = new CallLog();  
                    callLogBean.setId(id);  
                    callLogBean.setNumber(number);  
                    callLogBean.setName(cachedName);  
                    if (null == cachedName || "".equals(cachedName)) {  
                        callLogBean.setName(number);  
                    }  
                    callLogBean.setType(type);  
                    callLogBean.setDate(sfd.format(date));  
//                	Log.d("contact", "read call log:"+cachedName+"No:"+number);
                    callLogs.add(callLogBean);  
                }  
                if (callLogs.size() > 0) {  
                	Log.e("contact", "load calllog size:"+callLogs.size());  
                	ViewModel.getIns().refreshView(R.id.phone_calllog_list);
                	isCalllogNeedUpdate = true;
                	if(!mIsCalllogFirstLoaded) setCalllogFirstLoaded(true);
                }
            }  
            super.onQueryComplete(token, cookie, cursor);  
	   }
	}
    
    
    public List<CallLog> getCalllogs(){
    	if(callLogs == null ) callLogs = new ArrayList<CallLog>();
		return callLogs;
    }
    public boolean isContactsLoaded(){
    	return mIsContactsLoaded;
    }
	public boolean isCalllogFirstLoaded() {
		return mIsCalllogFirstLoaded;
	}
	public void setCalllogFirstLoaded(boolean mIsCalllogFirstLoaded) {
		this.mIsCalllogFirstLoaded = mIsCalllogFirstLoaded;
	}
    
	
	private void send2ServicePhoneState(int state){
		Log.e(tag, "sendPhoneState:"+state);
		byte[] buf = new byte[]{0x10,(byte)state};
		packAndSendMsg(buf, buf.length);
	}
	
	private void send2ServiceCallName(String name){
		if(name ==null || name.isEmpty()) return;
		Log.e(tag, "sendCallName:"+name);
//		int nameLen = name.getBytes().length;
//		byte[] fullNameBuf = name.getBytes();
//		int framesCount = 0;
//		if(nameLen%8==0) framesCount = nameLen/8;
//		else framesCount = nameLen/8+1;
//		
//		for(int i=0;i<framesCount;i++){
//			int startPos = i*8;
//			int len = 8;
//			if(startPos+8 > nameLen) 
//				len = nameLen - startPos;
//			sendCallNameFrame(nameLen, startPos, fullNameBuf, len);
//		}
		
		byte[] fullNameBuf = name.getBytes();
		sendCallNameFrame(fullNameBuf.length,0,fullNameBuf,fullNameBuf.length);
		
//		byte[] buf = new byte[nameLen+3];
//		buf[0] = 0x12;
//		buf[1] = (byte)nameLen;
//		buf[2] = 0;
//		System.arraycopy(name.getBytes(), 0, buf, 3, nameLen);
//		packAndSendMsg(buf, buf.length);
	}
	
	private void sendCallNameFrame(int length,int offset,byte[] data,int len){
		byte[] buf = new byte[len+3];
		buf[0] = 0x12;
		buf[1] = (byte)length;
		buf[2] = (byte)offset;
		System.arraycopy(data, offset, buf, 3, len);
		packAndSendMsg(buf, buf.length);
	}
	
	private void packAndSendMsg(byte[] message,int len){
	    byte[] szMsg = new byte[len + 5];
		szMsg[0] = (byte) 0xFF;
		szMsg[1] = (byte) 0x55;
		szMsg[2] = (byte) (len + 1);
		szMsg[3] = (byte) 0x35;
		System.arraycopy(message, 0, szMsg, 4, len);

		byte sum = 0;
		int s = 0;
		int i = 0;
		for (i = 2; i < len + 4; i++) {
			s += (szMsg[i] & 0xFF);
		}
		sum = (byte) (s & 0xFF);
		szMsg[len + 4] = sum;
		BluetoothModel.getInstance().sendMessage(szMsg);
   }
	
	
	public void onRecvMsg(byte[] buf, int length) {
		// TODO Auto-generated method stub
		//buf[0] 0x35

//    	final StringBuilder stringBuilder = new StringBuilder(buf.length);
//		for (byte byteChar : buf)
//			stringBuilder.append(String.format("%02X ", byteChar));
//		Log.i(tag,"phone Message: "+ stringBuilder.toString());
		int cmd = buf[1];
		switch(cmd){
		case 0x11://request phone state
			send2ServicePhoneState(mPhoneState);
			break;
		case 0x13:
			send2ServiceCallName(mCallName); 
		   break;//request call name; 
		}
	}
	
	
	
}
